package com.seguriapp.controller;

import static com.google.common.collect.Lists.newArrayList;

import java.util.List;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.seguriapp.entities.District;
import com.seguriapp.entities.SeguriAppEntity;
import com.seguriapp.entities.SeguriAppEntityType;
import com.seguriapp.services.EntityService;
import com.seguriapp.util.SearchFilterEntity;
import com.seguriapp.util.Util;

/**
 * Represents the controller for the "entity" entity
 * 
 * @author Tania Gonzales(taniadgv@gmail.com)
 */
@Controller
@RequestMapping("/entity")
public class EntityController {

  private static final Logger LOGGER = Logger.getLogger(EntityController.class);

  @Autowired
  private EntityService entityService;

  private long totalPages;

  @RequestMapping(value = "/list", method = RequestMethod.GET)
  @ResponseBody()
  public String listEntities() {
    final List<SeguriAppEntity> entitiesList = entityService.listEntities();
    if (entitiesList != null) {
      LOGGER.info("Size of entities list : " + entitiesList.size());
      return Util.parseEntityListToJson("entitiesList", entitiesList);
    }
    return StringUtils.EMPTY;
  }

  @RequestMapping(value = "/listByCategories", method = RequestMethod.POST)
  @ResponseBody()
  public String getEntitiesListByCategories(final @RequestBody String listParametersJs) {
    final List<SeguriAppEntity> entitiesList = getEntitiesListByCategory(listParametersJs);
    if (entitiesList != null) {
      LOGGER.info("Size of entities list : " + entitiesList.size());
      return Util.parseEntityListToJson("entitiesList", entitiesList);
    }
    return StringUtils.EMPTY;
  }

  @RequestMapping(value = "/list/byubication/{latitude}/{longitude}/{radio}", method = RequestMethod.GET)
  @ResponseBody()
  public String listEntitiesByUbication(@PathVariable double latitud, @PathVariable double longitud, @PathVariable double radio) {
    List<SeguriAppEntity> entityList = entityService.listEntitiesByUbication(latitud, longitud, radio);
    if (entityList != null) {
      LOGGER.info("Size of entities type list : " + entityList.size());
      return Util.parseEntityListToJson("entitiesList", entityList);
    }
    return StringUtils.EMPTY;
  }

  @RequestMapping(value = "/getEntityTypeList", method = RequestMethod.GET)
  @ResponseBody()
  public String getEntityTypeList() {
    final List<SeguriAppEntityType> entityTypeList = entityService.getSeguriAppEntityTypeList();
    if (entityTypeList != null) {
      LOGGER.info("Size of entities type list : " + entityTypeList.size());
      return Util.parseEntityListToJson("entityTypeList", entityTypeList);
    }
    return StringUtils.EMPTY;
  }

  @RequestMapping(value = "/getDistrictsList/{provinceId}", method = RequestMethod.GET)
  @ResponseBody()
  public String getDistrictsList(@PathVariable Long provinceId) {
    final List<District> districtsList = entityService.getDistrictsList(provinceId);
    if (districtsList != null) {
      LOGGER.info("Size of districts list : " + districtsList.size());
      return Util.parseEntityListToJson("districtsList", districtsList);
    }
    return StringUtils.EMPTY;
  }

  @RequestMapping(value = "/getEntitiesList", method = RequestMethod.POST)
  @ResponseBody()
  public String getEntitiesList(final @RequestBody String listParametersJs) {
    final List<SeguriAppEntity> entitiesList = getEntitiesListWithFilters(listParametersJs);
    if (entitiesList != null) {
      LOGGER.info("Size of entities list : " + entitiesList.size());
      return Util.parseEntityListToJson("entitiesList", entitiesList, totalPages);
    }
    return StringUtils.EMPTY;
  }

  private List<SeguriAppEntity> getEntitiesListByCategory(final String listParametersJs) {
    LOGGER.info("Request for entities: " + listParametersJs);
    if (listParametersJs == null || listParametersJs.isEmpty()) {
      return null;
    }
    final JSONObject root = JSONObject.fromObject(listParametersJs);
    final List<Long> categoriesIdsList = getCategoriesIdsList(root, "categoriesList");
    if (root.has("latitude") && root.has("longitude")) {
      double latitude = root.getDouble("latitude");
      double longitude = root.getDouble("longitude");
      return entityService.listEntitiesByCategories(categoriesIdsList, latitude, longitude);
    }
    Long userId = null;
    if (root.has("userId")) {
      userId = root.getLong("userId");
    }
    return entityService.listEntitiesByCategories(categoriesIdsList, userId);
  }

  private List<Long> getCategoriesIdsList(final JSONObject root, final String listName) {
    if (root.has(listName)) {
      final String categoriesListStr = root.getString(listName);
      if (categoriesListStr == null || categoriesListStr.isEmpty()) {
        return null;
      }
      final List<Long> categories = newArrayList();
      final String[] categoriesStr = categoriesListStr.split(Util.SEPARATOR);
      for (final String categoryStr : categoriesStr) {
        categories.add(Long.valueOf(categoryStr));
      }
      return categories;
    }
    return null;
  }

  private List<SeguriAppEntity> getEntitiesListWithFilters(final String listParametersJs) {
    LOGGER.info("Request for entities: " + listParametersJs);
    if (listParametersJs == null || listParametersJs.isEmpty()) {
      return null;
    }
    final JSONObject root = JSONObject.fromObject(listParametersJs);
    final List<Long> districtsIdsList = getCategoriesIdsList(root, "districtsIdsList");
    if (root.has("entityTypeId")) {
      SearchFilterEntity searchFilter = null;
      if (root.has(Util.PAGE) && root.has(Util.PAGE_SIZE) && root.has(Util.ASCENDING)) {
        final String columnSort = root.has(Util.COLUMN_SORT) ? root.getString(Util.COLUMN_SORT) : null;
        searchFilter = new SearchFilterEntity(root.getInt(Util.PAGE), root.getInt(Util.PAGE_SIZE), root.getBoolean(Util.ASCENDING), columnSort,
            districtsIdsList, root.getLong("entityTypeId"));
        totalPages = entityService.getEntitiesTotalPages(searchFilter);
      } else {
        searchFilter = new SearchFilterEntity(districtsIdsList, root.getLong("entityTypeId"), true);
      }
      return entityService.listEntities(searchFilter);
    }
    return null;
  }

}
